package com.ericsson.common.util;

import java.io.Serializable;
import java.time.DayOfWeek;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 基于java8的日期工具类
 * @author zhuguangrui
 *
 */
public class Jdk8DateUtils implements  Comparable<Jdk8DateUtils>, Serializable {
	private static final long serialVersionUID = 1L;
	private static final ZoneId zone = ZoneId.systemDefault();
	private static final ZoneOffset zoneOffset = ZoneOffset.UTC;
	private LocalDateTime dt;
	private static final Map<String,DateTimeFormatter> formatters = new ConcurrentHashMap<>();
	//第一部分：构造
	public static Jdk8DateUtils now(){
		return fromLocalDateTime(LocalDateTime.now());
	}
	public static Jdk8DateUtils yesterday(){
		return now().plusDays(-1);
	}
	public static Jdk8DateUtils tomorrow(){
		return now().plusDays(1);
	}
	public static Jdk8DateUtils fromLocalDateTime(LocalDateTime dt){
		Jdk8DateUtils d = new Jdk8DateUtils();
		d.dt = dt;
		return d;
	}
	public static Jdk8DateUtils of(int year, int month, int dayOfMonth, int hour, int minute, int second, int millisecond, int nanoOfSecond){
		LocalDateTime dt = LocalDateTime.of(year, month, dayOfMonth, hour, minute, millisecond, nanoOfSecond);
		return fromLocalDateTime(dt);
	}
	public static Jdk8DateUtils of(int year, int month, int dayOfMonth, int hour, int minute, int second, int millisecond){
		return of(year,month,dayOfMonth,hour,minute,second,millisecond,0);
	}
	public static Jdk8DateUtils of(int year, int month, int dayOfMonth, int hour, int minute, int second){
		return of(year,month,dayOfMonth,hour,minute,second,0,0);
	}
	public static Jdk8DateUtils of(int year, int month, int dayOfMonth, int hour, int minute){
		return of(year,month,dayOfMonth,hour,minute,0,0,0);
	}
	public static Jdk8DateUtils of(int year, int month, int dayOfMonth, int hour){
		return of(year,month,dayOfMonth,hour,0,0,0,0);
	}
	public static Jdk8DateUtils of(int year, int month, int dayOfMonth){
		return of(year,month,dayOfMonth,0,0,0,0,0);
	}
	public static Jdk8DateUtils of(LocalDate localDate, LocalTime localTime){
		return fromLocalDateTime(localTime.atDate(localDate));
	}
	public static Jdk8DateUtils ofInstant(Instant instant){
		return fromLocalDateTime(LocalDateTime.ofInstant(instant, zone));
	}
	public static Jdk8DateUtils ofEpochSecond(long epochSecond){
		return ofInstant(Instant.ofEpochSecond(epochSecond));
	}
	public static Jdk8DateUtils ofEpochMilli(long epochMilli) {
		return ofInstant(Instant.ofEpochMilli(epochMilli));
	}
	public static Jdk8DateUtils ofEpochSecond(long epochSecond, int nanoOfSecond){
		return ofInstant(Instant.ofEpochSecond(epochSecond,nanoOfSecond));
	}
	//第二部分：解析
	public static Jdk8DateUtils parseDateTime(String text){
		return fromLocalDateTime(LocalDateTime.parse(text));
	}
	public static Jdk8DateUtils parseDateTime(String text, String pattern){
		DateTimeFormatter format = findFormatter(pattern);
		return fromLocalDateTime(LocalDateTime.parse(text,format));
	}
	public static Jdk8DateUtils parseDate(String text){
		return fromLocalDateTime(LocalDate.parse(text).atStartOfDay());
	}
	public static Jdk8DateUtils parseDate(String text, String pattern){
		DateTimeFormatter format = findFormatter(pattern);
		return fromLocalDateTime(LocalDate.parse(text,format).atStartOfDay());
	}
	public static Jdk8DateUtils parseTime(String text){
		return fromLocalDateTime(LocalDate.now().atTime(LocalTime.parse(text)));
	}
	public static Jdk8DateUtils parseTime(String text, String pattern){
		DateTimeFormatter format = findFormatter(pattern);
		return fromLocalDateTime(LocalDate.now().atTime(LocalTime.parse(text,format)));
	}
	//第三部分：格式化
	public String formatDate(){
		return dt.toLocalDate().toString();
	}
	public String formatDate(String pattern){
		DateTimeFormatter format = findFormatter(pattern);
		return dt.toLocalDate().format(format);
	}
	public String formatDateTime(){
		return dt.toString();
	}
	public String formatDateTime(String pattern){
		DateTimeFormatter format = findFormatter(pattern);
		return dt.format(format);
	}
	public String formatTime(){
		return dt.toLocalTime().toString();
	}
	public String formatTime(String pattern){
		DateTimeFormatter format = findFormatter(pattern);
		return dt.toLocalTime().format(format);
	}
	//第四部分：转换成java日期
	public LocalDate toLocalDate(){
		return dt.toLocalDate();
	}
	public LocalTime toLocalTime(){
		return dt.toLocalTime();
	}
	public Instant toInstant(){
		return dt.toInstant(zoneOffset);
	}
	public Date toDate(){
		return Date.from(dt.toInstant(zoneOffset));
	}
	public LocalDateTime toLocalDateTime(){
		return dt;
	}
	//第五部分：计算
	public Jdk8DateUtils plusDays(int days){
		return fromLocalDateTime(dt.plusDays(days));
	}
	public Jdk8DateUtils plusYears(int years){
		return fromLocalDateTime(dt.plusYears(years));
	}
	public Jdk8DateUtils plusWeeks(int weeks){
		return fromLocalDateTime(dt.plusWeeks(weeks));
	}
	public Jdk8DateUtils plusMonths(int months){
		return fromLocalDateTime(dt.plusMonths(months));
	}
	public Jdk8DateUtils plusHours(int hours){
		return fromLocalDateTime(dt.plusHours(hours));
	}
	public Jdk8DateUtils plusMinutes(int minutes){
		return fromLocalDateTime(dt.plusMinutes(minutes));
	}
	public Jdk8DateUtils plusSeconds(int seconds){
		return fromLocalDateTime(dt.plusSeconds(seconds));
	}
	public Jdk8DateUtils plusNanos(int nanos){
		return fromLocalDateTime(dt.plusNanos(nanos));
	}
	//第六部分：调整值
	public Jdk8DateUtils previousOrSameMonday(){
		return fromLocalDateTime(dt.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY)));
	}
	public Jdk8DateUtils previousOrSameTuesday(){
		return fromLocalDateTime(dt.with(TemporalAdjusters.previousOrSame(DayOfWeek.TUESDAY)));
	}
	public Jdk8DateUtils previousOrSameWendesday(){
		return fromLocalDateTime(dt.with(TemporalAdjusters.previousOrSame(DayOfWeek.WEDNESDAY)));
	}
	public Jdk8DateUtils previousOrSameThursday(){
		return fromLocalDateTime(dt.with(TemporalAdjusters.previousOrSame(DayOfWeek.THURSDAY)));
	}
	public Jdk8DateUtils previousOrSameFriday(){
		return fromLocalDateTime(dt.with(TemporalAdjusters.previousOrSame(DayOfWeek.FRIDAY)));
	}
	public Jdk8DateUtils previousOrSameSaturday(){
		return fromLocalDateTime(dt.with(TemporalAdjusters.previousOrSame(DayOfWeek.SATURDAY)));
	}
	public Jdk8DateUtils previousOrSameSunday(){
		return fromLocalDateTime(dt.with(TemporalAdjusters.previousOrSame(DayOfWeek.SUNDAY)));
	}
	public Jdk8DateUtils previousOrSameWeekDay(DayOfWeek dayOfWeek){
		return fromLocalDateTime(dt.with(TemporalAdjusters.previousOrSame(dayOfWeek)));
	}
	public Jdk8DateUtils withYear(int year){
		return fromLocalDateTime(dt.withYear(year));
	}
	public Jdk8DateUtils withMonth(int month){
		return fromLocalDateTime(dt.withMonth(month));
	}
	public Jdk8DateUtils withDayOfMonth(int dayOfMonth){
		return fromLocalDateTime(dt.withDayOfMonth(dayOfMonth));
	}
	public Jdk8DateUtils withDayOfYear(int dayOfYear){
		return fromLocalDateTime(dt.withDayOfYear(dayOfYear));
	}
	public Jdk8DateUtils withHour(int hour){
		return fromLocalDateTime(dt.withHour(hour));
	}
	public Jdk8DateUtils withMinute(int minute){
		return fromLocalDateTime(dt.withMinute(minute));
	}
	public Jdk8DateUtils withSecond(int second){
		return fromLocalDateTime(dt.withSecond(second));
	}
	public Jdk8DateUtils withNanoOfSecond(int nanoOfSecond){
		return fromLocalDateTime(dt.withNano(nanoOfSecond));
	}
	//第七部分：时间段
	public long daysBetween(Jdk8DateUtils date){
		return dt.toLocalDate().toEpochDay()-date.dt.toLocalDate().toEpochDay();
	}
	public long secondsBetween(Jdk8DateUtils date){
		return dt.toEpochSecond(zoneOffset)-date.dt.toEpochSecond(zoneOffset);
	}
	//第八部分：比较
	public boolean isBefore(Jdk8DateUtils date){
		return dt.isBefore(date.dt);
	}
	public boolean isAfter(Jdk8DateUtils date){
		return dt.isAfter(date.dt);
	}
	public boolean isEqual(Jdk8DateUtils date){
		return dt.isEqual(date.dt);
	}
	@Override
	public int compareTo(Jdk8DateUtils date) {
		return dt.compareTo(date.dt);
	}
	//第九部分：提取值
	public long toEpochSecond(){
		return dt.toEpochSecond(zoneOffset);
	}
	public long toEpochMilli(){
		return dt.toInstant(zoneOffset).toEpochMilli();
	}
	public long getNano(){
		return dt.toInstant(zoneOffset).getNano();
	}
	//第十部分：
	
	private static DateTimeFormatter findFormatter(String pattern){
		DateTimeFormatter format = formatters.get(pattern);
		if(format==null){
			format = DateTimeFormatter.ofPattern(pattern);
			formatters.put(pattern, format);
		}
		return format;
	}

    public static void main(String[] args) {
        System.out.println(Jdk8DateUtils.now().secondsBetween(Jdk8DateUtils.now().previousOrSameMonday()));
    }
}

